﻿module game.controls;

import gamelib.queue;

enum Actions : char
{
    LEFT    = 'L',
    RIGHT   = 'R',
    UP      = 'U',
    DOWN    = 'D',
    ATTACK  = 'A',
    BOOST   = 'B',
    ESC     = 'E',
    INVALID = 255
}

struct ControlsState
{
private:
    static immutable MaxQueueLength = 10;
    GrowableCircularQueue!Actions mQueue;
    bool mLeft  = false;
    bool mRight = false;
    bool mUp    = false;
    bool mDown  = false;
    bool mAtck  = false;
    bool mBoost = false;
    bool mEsc   = false;
public:
    void processAction(in Actions ac, bool pressed) pure
    {
        if(pressed)
        {
            while(mQueue.length >= MaxQueueLength)
            {
                mQueue.pop();
            }
            mQueue.push(ac);
        }
        final switch(ac)
        {
            case ac.LEFT:
                mLeft = pressed;
                break;
            case ac.RIGHT:
                mRight = pressed;
                break;
            case ac.UP:
                mUp    = pressed;
                break;
            case ac.DOWN:
                mDown  = pressed;
                break;
            case ac.ATTACK:
                mAtck  = pressed;
                break;
            case ac.BOOST:
                mBoost = pressed;
                break;
            case ac.ESC:
                mEsc   = pressed;
                break;
            case ac.INVALID:
                assert(false);
        }
    }

    @property bool left()    const pure nothrow { return  mLeft && !mRight; }
    @property bool right()   const pure nothrow { return !mLeft &&  mRight; }
    @property bool up()      const pure nothrow { return  mUp && !mDown; }
    @property bool down()    const pure nothrow { return !mUp &&  mDown; }
    @property bool attack()  const pure nothrow { return  mAtck; }
    @property bool boost()   const pure nothrow { return  mBoost; }
    @property bool esc()     const pure nothrow { return  mEsc; }

    @property auto queue()   const pure nothrow { return mQueue.range; }
    void clearQueue() pure { mQueue.length = 0; }
}
